<template>
  <div ref="uploadImageRef" class="upload-image" :class="[props.isNone ? 'is-none' : 'is-box']">
    <el-upload
      ref="uploadRef"
      v-model:file-list="modelFileListCustomer"
      :auto-upload="false"
      :accept="uploadAccept"
      :limit="props.limit"
      :drag="!props.isNone"
      multiple
      list-type="text"
      :class="[uploadClass]"
      @change="changeFileHandle"
    >
      <slot name="default">
        <div class="text-color-placeholder">
          <el-icon size="35"><UploadFilled /></el-icon><br>
          <div class="fs-12">
            <div>点击或拖拽上传</div>
            <span v-if="props.maxSize !== Infinity">小于{{ sizeUnit.value + sizeUnit.unit }}的</span>
            <span v-if="props.accept">({{ props.accept }})类型文件</span>
            <span v-else>任意类型文件</span>
          </div>
        </div>
      </slot>
    </el-upload>
  </div>
</template>

<script lang="ts" setup>
import { computed, ref, withDefaults } from 'vue'
import { UploadFilled } from '@element-plus/icons-vue'
import { ElUpload, UploadUserFile } from 'element-plus'
import { dataset } from '@yk/components/upload/accept'
import { ObjectUtil } from '@utils/object-util'

const props = withDefaults(defineProps<{
  modelValue: UploadUserFile[],
  uploadClass?: string,
  accept?: string,
  width?: string,
  height?: string,
  maxSize?: number,
  limit?: number,
  isNone?: boolean,
  onError?(error: Error, file: UploadUserFile): void
}>(), {
  width: '248px',
  height: '148px',
  uploadClass: '',
  maxSize: Infinity,
  limit: Infinity,
  isNone: false,
  accept: ''
})

const emits = defineEmits(['update:modelValue', 'change'])

const uploadImageRef = ref<HTMLDivElement>()
const uploadRef = ref<InstanceType<typeof ElUpload>>()

onMounted(() => {
  uploadImageRef.value.style.setProperty('--upload-image-size-w', props.width)
  uploadImageRef.value.style.setProperty('--upload-image-size-h', props.height)
})

// region TODO 数据同步
const modelFileListCustomer = computed({
  get (): UploadUserFile[] {
    return props.modelValue
  },
  set (val: UploadUserFile[]) {
    emits('update:modelValue', val)
  }
})
// 移除文件
function changeFileHandle (file: UploadUserFile) {
  let error = null
  if (!verifyFileType(file.raw)) {
    error = Error('文件类型应为' + props.accept)
  } else if (file.size > props.maxSize) {
    const unitVal = ObjectUtil.matchUnit(props.maxSize, 'bit', 'maxCarry', { carryNumber: 1024, fractionDigits: 2 })
    error = Error('文件大小不能超过' + unitVal.value + unitVal.unit)
  }
  if (error) {
    uploadRef.value.handleRemove(file.raw)
    if (props.onError) props.onError(error, file)
  } else {
    emits('change', file)
  }
}
// endregion

// region TODO 文件类型限制
const sizeUnit = ref({ unit: '', value: 0 })
onMounted(() => {
  sizeUnit.value = ObjectUtil.matchUnit(props.maxSize, 'bit', 'maxCarry', { fractionDigits: 2, carryNumber: 1024 })
})
const uploadAccept = computed(() => props.accept.split(',').map(key => dataset[key]).join(','))
// 检查类型是否合法，true合法，false不合法
function verifyFileType (file: File): boolean {
  if (!props.accept) return true
  return props.accept.split(',').includes(file.name.replace(/^.*\.(\w*)$/, '$1'))
}
// endregion

</script>

<style lang="scss" scoped>
.upload-image {
  margin-bottom: -8px;
  &.is-box {
    width: var(--upload-image-size-w);
    height: var(--upload-image-size-h);
  }
  &.is-none {
    ::v-deep(.el-upload-list ) {
      display: none;
    }
  }
}
::v-deep(.el-upload--text ) {
  .el-upload-dragger {
    width: var(--upload-image-size-w);
    height: var(--upload-image-size-h);
    display: flex;
    align-items: center;
    justify-content: center;
  }
}
</style>
